package java_thinking.unit_17._17_11_13;

import java.lang.ref.*;
import java.util.LinkedList;

/**
 * @Desc:   持有引用：持有引用的作用是在执行gc之后允许你继续持有(可能)被回收了的对象的引用，而将对象实例清出内存，持有
 *                  引用提供了与垃圾回收器之间有限的交互；(结合GCTheory.java)
 *          背景：
 *              在JDK 1.2以前的版本中，若一个对象不被任何变量引用，那么程序就无法再使用这个对象。也就是说，只有对象处
 *              于可触及(reachable)状态，程序才能使用它。从JDK 1.2版本开始，把对象的引用分为4种级别，从而使程序能更
 *              加灵活地控制对象的生命周期。
 *          必看：
 *              https://blog.csdn.net/syc001/article/details/78121203
 *          强引用与软引用最根本的区别：
 *              强引用即使在虚拟机抛出OutOfMemoryError之后虚拟机也不会对其进行清理，而软引用会在虚拟机抛出
 *              OutOfMemoryError之前回收软可及对象；
 *
 *          对象是可获得的，是指此对象可在程序中的某处找到，这意味着在栈中有一个普通的引用，而它正指向此对象
 *          如果一个对象是可获得的，垃圾回收器就不能释放它，因为它还在用；
 *          如果想继续持有某个对象的引用，希望以后还能访问到该对象，但是也希望能够允许垃圾回收期释放它，这时就应该使用
 *          Reference对象，这样你可以继续使用该对象，而在内存消耗殆尽的时候又允许释放该对象，普通的引用是指没有经过
 *          Reference包装过的引用；
 *          https://blog.csdn.net/guohenu/article/details/7364967
 *
 *          1.SoftReference:用以实现内存敏感的高速缓存
 *          2.WeakReference:是为实现"规范映射"而设计的，它不妨碍垃圾回收期回收映射的"键"或值。规范映射中对象的实例可以
 *              在程序的多出被同时使用，以节省存储空间，
 *          3.PhantomReference:用以调度回收前的清理工作，他比java终止机制更灵活
 *          4.ReferenceQueue：使用ReferenceQueue清除失去了(被垃圾回收器回收了的)软引用对象的SoftReference(它也是一个对象，
 *              若不回收也会占满内存)；使用SoftReference和WeakReference时可以选择是否要将他们放入ReferenceQueue用作回收前
 *              清理工作的工具，而PhantomReference只能依赖于ReferenceQueue
 *
 * @author: cww
 * @DateTime: 2019-04-21 18:36
 */
class VeryBig {
    private static final int SIZE = 10000;
    private long[] la = new long[SIZE];
    private String ident;
    public VeryBig(String id) {
        ident = id;
    }

    @Override
    public String toString() {
        return ident;
    }
    @Override
    protected void finalize() {
        System.out.println("Finalizing " + ident);
    }
}
/**
 * @author asd730520@live.com
 */
public class References {
    private static ReferenceQueue<VeryBig> rq = new ReferenceQueue<>();
    public static void checkQueue() {
        Reference<? extends VeryBig> inq = rq.poll();
        if (inq != null) {
            System.out.println("In queue: " + inq.get());
        }
    }

    public static void main(String[] args) {
        int size = 10;
        if (args.length > 0) {
            size = new Integer(args[0]);
        }
        LinkedList<SoftReference<VeryBig>> sa = new LinkedList<>();
        for (int i = 0; i < size; i++) {
            sa.add(new SoftReference<VeryBig>(new VeryBig("Soft " + i),rq));
            System.out.println("Just created: " + sa.getLast());
            checkQueue();
        }
        LinkedList<WeakReference<VeryBig>> wa = new LinkedList<>();
        for (int i = 0; i > size; i++) {
            wa.add(new WeakReference<>(new VeryBig("Weak " + i),rq));
            System.out.println("Just created: " + wa.getLast());
        }
        SoftReference<VeryBig> s = new SoftReference<>(new VeryBig("Soft"));
        WeakReference<VeryBig> w = new WeakReference<>(new VeryBig("Weak"));
        System.gc();
        LinkedList<PhantomReference<VeryBig>> pa = new LinkedList<>();
        for (int i = 0; i < size; i++) {
            pa.add(new PhantomReference<>(new VeryBig("Phantom " + i),rq));
            System.out.println("Just created: " + pa.getLast());
            checkQueue();
        }
    }
}
